package com.shunda.ysdgj.manager.service.impl.goods;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.base.MPJBaseService;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.shunda.ysdgj.common.exception.CustomException;
import com.shunda.ysdgj.common.util.ValidateUtil;
import com.shunda.ysdgj.manager.mapper.goods.GoodsSpecMapper;
import com.shunda.ysdgj.manager.service.goods.GoodsSpecItemService;
import com.shunda.ysdgj.manager.service.goods.GoodsSpecService;
import com.shunda.ysdgj.model.dto.base.IdsDto;
import com.shunda.ysdgj.model.dto.goods.GoodsSpecFindDto;
import com.shunda.ysdgj.model.entity.goods.GoodsSpec;
import com.shunda.ysdgj.model.entity.goods.GoodsSpecCategory;
import com.shunda.ysdgj.model.entity.goods.GoodsSpecItem;
import com.shunda.ysdgj.model.vo.ResultCodeEnum;
import com.shunda.ysdgj.model.vo.goods.GoodsSpecItemVo;
import com.shunda.ysdgj.model.vo.goods.GoodsSpecVo;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
@RequiredArgsConstructor
public class GoodsSpecServiceImpl
        extends MPJBaseServiceImpl<GoodsSpecMapper, GoodsSpec>
        implements GoodsSpecService, MPJBaseService<GoodsSpec> {

    private final GoodsSpecItemService goodsSpecItemService;

    public List<GoodsSpecVo> findByCategoryId(Long id) {
        MPJLambdaWrapper<GoodsSpec> baseWrapper = JoinWrappers
                .lambda(GoodsSpec.class)
                .select(GoodsSpec::getId, GoodsSpec::getSpecName)
                .eq(GoodsSpec::getSpecCategoryId, id)
                .orderByAsc(GoodsSpec::getSpecSort);
        List<GoodsSpecVo> specList = getBaseMapper().selectJoinList(GoodsSpecVo.class, baseWrapper);
        for (GoodsSpecVo spec : specList) {
            spec.setSpecItems(goodsSpecItemService.findVoBySpecId(spec.getId()));
        }
        return specList;
    }

    public IPage<GoodsSpec> findByPage(GoodsSpecFindDto goodsSpecFindDto) {
        if (ValidateUtil.isNotLong(goodsSpecFindDto.getCurrent())) {
            goodsSpecFindDto.setCurrent(1L);
        }
        if (ValidateUtil.isNotLong(goodsSpecFindDto.getSize())) {
            goodsSpecFindDto.setSize(10L);
        }
        MPJLambdaWrapper<GoodsSpec> baseWrapper = JoinWrappers
                .lambda(GoodsSpec.class)
                .select(
                        GoodsSpec::getId, GoodsSpec::getSpecCategoryId,
                        GoodsSpec::getSpecName, GoodsSpec::getSpecSort, GoodsSpec::getCreated,
                        GoodsSpec::getUpdated, GoodsSpec::getVersion
                ).select(GoodsSpecCategory::getSpecCategoryName, GoodsSpecCategory::getSpecCategoryType)
                .leftJoin(GoodsSpecCategory.class, GoodsSpecCategory::getId, GoodsSpec::getSpecCategoryId)
                .orderByAsc(GoodsSpec::getSpecSort);
        if (ValidateUtil.isInteger(goodsSpecFindDto.getSpecCategoryType())) {
            baseWrapper.eq(GoodsSpecCategory::getSpecCategoryType, goodsSpecFindDto.getSpecCategoryType());
        }
        if (ValidateUtil.isLong(goodsSpecFindDto.getSpecCategoryId())) {
            baseWrapper.eq(GoodsSpec::getSpecCategoryId, goodsSpecFindDto.getSpecCategoryId());
        }
        if (StrUtil.isNotEmpty(goodsSpecFindDto.getSpecName())) {
            baseWrapper.like(GoodsSpec::getSpecName, goodsSpecFindDto.getSpecName());
        }
        IPage<GoodsSpec> page = new Page<>(goodsSpecFindDto.getCurrent(), goodsSpecFindDto.getSize());
        IPage<GoodsSpec> goodsSpecPage = getBaseMapper().selectJoinPage(page, GoodsSpec.class, baseWrapper);
        for (GoodsSpec goodsSpec : goodsSpecPage.getRecords()) {
            goodsSpec.setSpecItems(goodsSpecItemService.findBySpecId(goodsSpec.getId()));
        }
        return goodsSpecPage;
    }

    @Transactional
    public boolean add(GoodsSpec goodsSpec) {
        if (ValidateUtil.isBlank(goodsSpec.getSpecName())
                || ValidateUtil.isNotInteger(goodsSpec.getSpecSort())
                || goodsSpec.getSpecItems().isEmpty()) {
            throw new CustomException(ResultCodeEnum.PARAM_ERROR);
        }
        goodsSpec.setId(null);
        if (!save(goodsSpec)) {
            return false;
        }
        List<GoodsSpecItem> specItems = goodsSpec.getSpecItems();
        for (GoodsSpecItem specItem : specItems) {
            specItem.setId(null);
            specItem.setSpecCategoryId(goodsSpec.getSpecCategoryId());
            specItem.setSpecId(goodsSpec.getId());
        }
        return goodsSpecItemService.add(specItems);
    }

    @Transactional
    public boolean modify(GoodsSpec goodsSpec) {
        if (ValidateUtil.isNotLong(goodsSpec.getId())
                || ValidateUtil.isBlank(goodsSpec.getSpecName())
                || ValidateUtil.isNotInteger(goodsSpec.getSpecSort())
                || goodsSpec.getSpecItems().isEmpty()) {
            throw new CustomException(ResultCodeEnum.PARAM_ERROR);
        }
        if (!updateById(goodsSpec)) {
            return false;
        }
        return goodsSpecItemService.modify(goodsSpec, goodsSpec.getSpecItems());
    }

    @Transactional
    public boolean deleteByIds(IdsDto idsDto) {
        List<Long> ids = idsDto.getIds();
        if (ids.isEmpty()) {
            throw new CustomException(ResultCodeEnum.PARAM_ERROR);
        }
        removeByIds(ids);
        return goodsSpecItemService.deleteBySpecIds(ids);
    }

    public Long countByCategoryIds(List<Long> ids) {
        return lambdaQuery().in(GoodsSpec::getSpecCategoryId, ids).count();
    }

}
